package demo1;
/*
这是关于父类子类的相关测试
执行顺序：
父类静态代码块  >  子类静态代码块  >  父类实例代码块  >  父类构造方法  >  子类实例代码块  >  子类构造方法
如果父类的构造方法含参数，则子类的构造方法必须显式定义。反之，若父类的构造方法无参数或则没有进行显式定义，则子类就不需要显式定义。
 */

//这里不能用protected修饰
class Animal{
    String name;
    static int age;
    int data1 = 1;
    static int data2 = 2;
    public static void fun()
    {
        System.out.println("这是父类的静态方法");
    }
    public void SetName(String name)
    {
        this.name = name;
    }
    static
    {
        System.out.println("这是一个父类的静态代码块");
    }
    {
        System.out.println("这是一个父类的实例代码块！");
    }

    public void eat() {
        System.out.println(name+"正在吃饭");
    }
    public Animal(int a){
        System.out.println("这是一个父类构造方法!");
    }
}



class Cat extends Animal{
    public static void fun1()
    {
        System.out.println("这是一个子类的静态方法!");
    }
    static {
        System.out.println("这是一个子类的静态代码块!");
    }
    {
        System.out.println("这是一个子类的实例代码块");
    }

    public Cat(int b)
    {
        super(1);//调用父类构造方法
        System.out.println("这是一个子类的构造方法!");
    }
    //重写
    @Override
    public void eat() {//eat方法的重写
        System.out.println(name + "正在吃猫粮");
    }
}


class Dog extends Animal{
    public Dog()
    {
        super(1);
    }

    public void eat(){
        System.out.println(name+"正在吃狗粮");
    }
}
public class Test {

    public static void function(Animal animal)
    {
        animal.eat();
    }

    public static void main(String[] args) {
        Cat cat = new Cat(1);
        Dog dog = new Dog();
//    cat.SetName("喵喵");
//    cat.eat();
//    //访问父类的静态成员。这两种方法都可以
//    System.out.println(Animal.data2);
//    System.out.println(cat.data2);
//    //访问父类的静态方法,这两种方法都可以
//        cat.fun();
//        Animal.fun();
//        //访问子类的静态方法,这两种方法都可以
//        cat.fun1();
//        Cat.fun1();

        //向上转型:方法一：直接赋值。 方法二：间接赋值，将子类的引用对象直接传参，用父类的引用对象接收
        //实现多态 调用同一个方法实现不同的功能
        function(cat);
        function(dog);
    }
}

